#include "mipser.h"

int isCalcRes(Valeur *v){
    return (v->isRes && !v->Specific.isConstant);
}

void push(char *v){
    fprintf(out, "\taddi $sp, $sp, -4\n"); // PUSH
    fprintf(out, "\tsw %s, 0($sp)\n",v);   // PUSH
}

void pop(char *v){
    fprintf(out, "\tlw %s, 0($sp)\n",v);   // POP
    fprintf(out, "\taddi $sp, $sp, 4\n");  // POP
}

void mipser(Quad q)
{
    int sp=0;
    out = fopen("tmp.s", "w");
    printf("\nGeneration bitches !\n");
    fprintf(out, "\t.data\n_jmpline_:\t.asciiz \"\\n\"\n.text\n");   // POP

    int label=0;

    int i;
    for(; q!=NULL; q=q->next){
        switch(q->op){
            //mbox
            case 'm':
                //empile le sp de reference
                fprintf(out, "#empile conservation de référence\n");
                push("$s0");
                fprintf(out, "#empilement $ra\n");
                push("$ra");
                //ici on empile les args et on prépare la valeur de retour
                //empilement des outputs
                fprintf(out, "#empilement output\n");
                fprintf(out, "\taddi $sp, $sp, -4\n");
                printf("fct %s\n", q->res->name);
                printf("inp %d\n", q->res->Specific.nbParams[0]);
                printf("out %d\n", q->res->Specific.nbParams[1]);
                printf("loc %d\n", q->res->Specific.nbParams[2]);
                break;

            case 'a':
                //empilement des inputs
                fprintf(out, "#empilement inputs\n");
                //si constante
                if(q->res->Specific.isConstant){
                    fprintf(out, "\taddi $sp, $sp, -4\n");
                    fprintf(out, "\tli $t0, %d\n", q->res->Value.integer);
                }else if(isCalcRes(q->res)){
                    pop("$t0");
                    fprintf(out, "\taddi $sp, $sp, -4\n");
                }else{
                    fprintf(out, "\taddi $sp, $sp, -4\n");
                    fprintf(out, "\tlw $t0, %d($s0)\n", -q->res->Memory.sp);
                }
                fprintf(out, "\tsw $t0, 0($sp)\n");
                break;

            case 'b':
                fprintf(out, "#fin empilement inputs\n");
                fprintf(out, "\tjal %s\n", q->res->name);
                //récupération output
                fprintf(out, "#pop output\n");
                pop("$t0");
                //récupération du $ra
                fprintf(out, "#pop ra\n");
                pop("$ra");
                //récupération de la valeur
                fprintf(out, "#pop référence\n");
                pop("$s0");
                push("$t0");
                break;

            //var global
            case 'g':
//              q->res->Specific.nbParams[0]++;
                /*q->res->Memory.sp = sp;
                sp += 4;*/
                break;

            //var input
            case 'i':
                q->res->Memory.sp = sp;
                sp += 4;
                break;

            //var output
            case 'o':
                q->res->Memory.sp = sp;
                sp += 4;
                break;

            //var locale
            case 'l':
                fprintf(out, "#empilement locale\n");
                fprintf(out, "\taddi $sp, $sp, -4\n");
                q->res->Memory.sp = sp;
                sp += 4;
                break;

            //fin de fonction
            case 'e':
                sp = 0;
                //dépilement des locales
                for(i=0; i<q->res->Specific.nbParams[2]; ++i){
                    fprintf(out, "#dépilement locale\n");
                    fprintf(out, "\taddi $sp, $sp, 4\n");
                }
                //dépilement des inputs
                for(i=0; i<q->res->Specific.nbParams[0]; ++i){
                    fprintf(out, "#dépilement inputs\n");
                    fprintf(out, "\taddi $sp, $sp, 4\n");
                }
                fprintf(out, "\tjr $ra\n");
                break;

            case 'p':
                if(q->arg1==NULL){
                    fprintf(out, "\tli $v0, 4\n");
                    fprintf(out, "\tla $a0, _jmpline_\n");
                    fprintf(out, "\tsyscall\n");
                    break;
                }
                fprintf(out, "\tli $v0, 1\n");
                if(q->arg1->Specific.isConstant){ // ! CONSTANT
                    fprintf(out, "\tli $a0, %d\n",q->arg1->Value.boolean);
                }else if(isCalcRes(q->arg1)){      // ! RESULT
                    pop("$a0");
                }else{                            // ! VARIABLE
                    fprintf(out, "\tlw $a0, %d($s0)\n", -q->arg1->Memory.sp);
                }
                fprintf(out,"\tsyscall\n");
                break;

            case 's':
                fprintf(out, "\tli $v0, 5\n");
                fprintf(out, "\tsyscall\n");
                push("$v0");
                break;


            case 'f':
                fprintf(out, "\n%s:\n", q->res->name);
                sp = -(q->res->Specific.nbParams[0]+q->res->Specific.nbParams[1]-1)*4;
                fprintf(out, "\tmove $s0, $sp\n");
                break;

            case 'x':
                fprintf(out, "\tli $v0, 10\n");
                fprintf(out, "\tsyscall\n");
                break;

            case '+':
                if(q->arg1->Specific.isConstant && q->arg2->Specific.isConstant){ // CONSTANT + CONSTANT
                    fprintf(out, "\tli $t0, %d\n",q->arg1->Value.integer+q->arg2->Value.integer);
                }else if(q->arg1->Specific.isConstant){
                    if(isCalcRes(q->arg2)){ // CONSTANT + RESULT
                        pop("$t2");
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tadd $t0, $t1, $t2\n");
                    }else{ // CONSTANT + VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tadd $t0, $t1, $t2\n");
                    }
                }else if(q->arg2->Specific.isConstant){
                    if(isCalcRes(q->arg1)){ // RESULT + CONSTANT
                        pop("$t1");
                        fprintf(out, "\taddi $t0, $t1, %d\n", q->arg2->Value.integer);
                    }else{ // VARIABLE + CONSTANT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\taddi $t0, $t1, %d\n", q->arg2->Value.integer);
                    }
                }else{
                    if(isCalcRes(q->arg1)&&isCalcRes(q->arg2)){ // RESULT + RESULT
                        pop("$t2");
                        pop("$t1");
                        fprintf(out, "\tadd $t0, $t1, $t2\n");
                    }else if(isCalcRes(q->arg1)){ // RESULT + VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t1");
                        fprintf(out, "\tadd $t0, $t1, $t2\n");
                    }else if(isCalcRes(q->arg2)){ // VARIABLE + RESULT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        pop("$t2");
                        fprintf(out, "\tadd $t0, $t1, $t2\n");
                    }else{ // VARIABLE + VARIABLE
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        fprintf(out, "\tadd $t0, $t1, $t2\n");
                    }
                }
                push("$t0");
                break;

            case '-':
                if(q->arg1->Specific.isConstant && q->arg2->Specific.isConstant){ // CONSTANT - CONSTANT
                    fprintf(out, "\tli $t0, %d\n",q->arg1->Value.integer-q->arg2->Value.integer);
                }else if(q->arg1->Specific.isConstant){
                    if(isCalcRes(q->arg2)){ // CONSTANT - RESULT
                        pop("$t2");
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tsub $t0, $t1, $t2\n");
                    }else{ // CONSTANT - VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tsub $t0, $t1, $t2\n");
                    }
                }else if(q->arg2->Specific.isConstant){
                    if(isCalcRes(q->arg1)){ // RESULT - CONSTANT
                        pop("$t1");
                        fprintf(out, "\tli $t0, %d\n", q->arg2->Value.integer);
                        fprintf(out, "\tsub $t0, $t1, $t0\n");
                    }else{ // VARIABLE - CONSTANT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tli $t0, %d\n", q->arg2->Value.integer);
                        fprintf(out, "\tsub $t0, $t1, $t0\n");
                    }
                }else{
                    if(isCalcRes(q->arg1)&&isCalcRes(q->arg2)){ // RESULT - RESULT
                        pop("$t2");
                        pop("$t1");
                        fprintf(out, "\tsub $t0, $t1, $t2\n");
                    }else if(isCalcRes(q->arg1)){ // RESULT - VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t1");
                        fprintf(out, "\tsub $t0, $t1, $t2\n");
                    }else if(isCalcRes(q->arg2)){ // VARIABLE - RESULT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        pop("$t2");
                        fprintf(out, "\tsub $t0, $t1, $t2\n");
                    }else{ // VARIABLE - VARIABLE
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        fprintf(out, "\tsub $t0, $t1, $t2\n");
                    }
                }
                push("$t0");
                break;

            case '*':
                if(q->arg1->Specific.isConstant && q->arg2->Specific.isConstant){ // CONSTANT * CONSTANT
                    fprintf(out, "\tli $t0, %d\n",q->arg1->Value.integer*q->arg2->Value.integer);
                }else if(q->arg1->Specific.isConstant){
                    if(isCalcRes(q->arg2)){ // CONSTANT * RESULT
                        pop("$t2");
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tmul $t0, $t1, $t2\n");
                    }else{ // CONSTANT * VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tmul $t0, $t1, $t2\n");
                    }
                }else if(q->arg2->Specific.isConstant){
                    if(isCalcRes(q->arg1)){ // RESULT * CONSTANT
                        pop("$t1");
                        fprintf(out, "\tmul $t0, $t1, %d\n", q->arg2->Value.integer);
                    }else{ // VARIABLE * CONSTANT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tmul $t0, $t1, %d\n", q->arg2->Value.integer);
                    }
                }else{
                    if(isCalcRes(q->arg1)&&isCalcRes(q->arg2)){ // RESULT * RESULT
                        pop("$t2");
                        pop("$t1");
                        fprintf(out, "\tmul $t0, $t1, $t2\n");
                    }else if(isCalcRes(q->arg1)){ // RESULT * VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t1");
                        fprintf(out, "\tmul $t0, $t1, $t2\n");
                    }else if(isCalcRes(q->arg2)){ // VARIABLE * RESULT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        pop("$t2");
                        fprintf(out, "\tmul $t0, $t1, $t2\n");
                    }else{ // VARIABLE * VARIABLE
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        fprintf(out, "\tmul $t0, $t1, $t2\n");
                    }
                }
                push("$t0");
                break;

            case BOOLOP+VEE:
                if(q->arg1->Specific.isConstant && q->arg2->Specific.isConstant){ // CONSTANT || CONSTANT
                    int t;
                    if(q->arg1->Value.boolean || q->arg2->Value.boolean) t=1;
                    else                                                 t=0;
                    fprintf(out, "\tli $t0, %d\n",t);
                }else if(q->arg1->Specific.isConstant){
                    if(isCalcRes(q->arg2)){ // CONSTANT || RESULT
                        pop("$t2");
                        if(q->arg1->Value.boolean)
                            fprintf(out, "\tli $t0, 1\n");
                        else
                            fprintf(out, "\tdiv $t0, $t2, $t2\n");
                    }else{ // CONSTANT || VARIABLE
                        if(q->arg1->Value.boolean)
                            fprintf(out, "\tli $t0, 1\n");
                        else{
                            fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                            fprintf(out, "\tdiv $t0, $t2, $t2\n");
                        }
                    }
                }else if(q->arg2->Specific.isConstant){
                    if(isCalcRes(q->arg1)){ // RESULT || CONSTANT
                        pop("$t1");
                        if(q->arg2->Value.boolean)
                            fprintf(out, "\tli $t0, 1\n");
                        else
                            fprintf(out, "\tdiv $t0, $t1, $t1\n");
                    }else{ // VARIABLE || CONSTANT
                        if(q->arg2->Value.boolean)
                            fprintf(out, "\tli $t0, 1\n");
                        else{
                            printf("fdgkfdgkfdg\n");
                            fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                            fprintf(out, "\tdiv $t0, $t1, $t1\n");
                        }
                    }
                }else{
                    if(isCalcRes(q->arg1)&&isCalcRes(q->arg2)){ // RESULT || RESULT
                        pop("$t2");
                        pop("$t1");
                        fprintf(out, "\tdiv $t1, $t1, $t1\n"); // On force t1 en booléen
                        fprintf(out, "\tdiv $t2, $t2, $t2\n"); // On force t2 en booléen
                        fprintf(out, "\tadd $t0, $t1, $t2\n"); //   t0 = t1+t2 (0/1/2)
                        fprintf(out, "\tdiv $t0, $t0, $t0\n"); // On force t0 en booléen
                    }else if(isCalcRes(q->arg1)){ // RESULT || VARIABLE
                        pop("$t1");
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        fprintf(out, "\tdiv $t1, $t1, $t1\n"); // On force t1 en booléen
                        fprintf(out, "\tdiv $t2, $t2, $t2\n"); // On force t2 en booléen
                        fprintf(out, "\tadd $t0, $t1, $t2\n"); //   t0 = t1+t2 (0/1/2)
                        fprintf(out, "\tdiv $t0, $t0, $t0\n"); // On force t0 en booléen
                    }else if(isCalcRes(q->arg2)){ // VARIABLE || RESULT
                        pop("$t2");
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tdiv $t1, $t1, $t1\n"); // On force t1 en booléen
                        fprintf(out, "\tdiv $t2, $t2, $t2\n"); // On force t2 en booléen
                        fprintf(out, "\tadd $t0, $t1, $t2\n"); //   t0 = t1+t2 (0/1/2)
                        fprintf(out, "\tdiv $t0, $t0, $t0\n"); // On force t0 en booléen
                    }else{ // VARIABLE || VARIABLE
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        fprintf(out, "\tdiv $t1, $t1, $t1\n"); // On force t1 en booléen
                        fprintf(out, "\tdiv $t2, $t2, $t2\n"); // On force t2 en booléen
                        fprintf(out, "\tadd $t0, $t1, $t2\n"); //   t0 = t1+t2 (0/1/2)
                        fprintf(out, "\tdiv $t0, $t0, $t0\n"); // On force t0 en booléen
                    }
                }
                push("$t0");
                break;

            case BOOLOP+NEG:
                if(q->arg1->Specific.isConstant){ // ! CONSTANT
                    int t;
                    if(q->arg1->Value.boolean) t=0;
                    else                       t=1;
                    fprintf(out, "\tli $t0, %d\n",t);
                }else if(isCalcRes(q->arg1)){      // ! RESULT
                    pop("$t0");
                    fprintf(out, "\tdiv $t0, $t0, $t0\n");
                    fprintf(out, "\tmul $t0, $t0, -1\n");  // GHETTO STYLE BINARY SWITCH
                    fprintf(out, "\taddi $t0, $t0, 1\n");
                }else{                            // ! VARIABLE
                    fprintf(out, "\tlw $t0, %d($s0)\n", -q->arg1->Memory.sp);
                    fprintf(out, "\tdiv $t0, $t0, $t0\n");
                    fprintf(out, "\tmul $t0, $t0, -1\n");  // GHETTO STYLE BINARY SWITCH
                    fprintf(out, "\taddi $t0, $t0, 1\n");
                }
                push("$t0"); 
                break;

            case BOOLOP+POS:
                if(q->arg1->Specific.isConstant){ // CONSTANT
                    int t;
                    if(q->arg1->Value.boolean) t=1;
                    else                       t=0;
                    fprintf(out, "\tli $t0, %d\n",t);
                }else if(isCalcRes(q->arg1)){      // RESULT
                    pop("$t0");
                    fprintf(out, "\tdiv $t0, $t0, $t0\n");
                }else{                            // VARIABLE
                    fprintf(out, "\tlw $t0, %d($s0)\n", -q->arg1->Memory.sp);
                    fprintf(out, "\tdiv $t0, $t0, $t0\n");
                }
                push("$t0"); 
                break;

            case BOOLOP+EQ:
                if(q->arg1->Specific.isConstant && q->arg2->Specific.isConstant){ // CONSTANT == CONSTANT
                    if(q->arg1->Value.integer == q->arg2->Value.integer)
                        fprintf(out, "\tli $t0, 1\n");
                    else
                        fprintf(out, "\tli $t0, 0\n");
                }else if(q->arg1->Specific.isConstant){
                    if(isCalcRes(q->arg2)){ // CONSTANT == RESULT
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        pop("$t2");

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // CONSTANT == VARIABLE
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else if(q->arg2->Specific.isConstant){
                    if(isCalcRes(q->arg1)){ // RESULT == CONSTANT
                        pop("$t1");
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE == CONSTANT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else{
                    if(isCalcRes(q->arg1)&&isCalcRes(q->arg2)){ // RESULT == RESULT
                        pop("$t2");
                        pop("$t1");

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg1)){ // RESULT == VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t1");

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg2)){ // VARIABLE == RESULT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t2");

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE == VARIABLE
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }
                push("$t0");
                break;

            case BOOLOP+NEQ:
                if(q->arg1->Specific.isConstant && q->arg2->Specific.isConstant){ // CONSTANT != CONSTANT
                    if(q->arg1->Value.integer != q->arg2->Value.integer)
                        fprintf(out, "\tli $t0, 1\n");
                    else
                        fprintf(out, "\tli $t0, 0\n");
                }else if(q->arg1->Specific.isConstant){
                    if(isCalcRes(q->arg2)){ // CONSTANT != RESULT
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        pop("$t2");

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // CONSTANT != VARIABLE
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else if(q->arg2->Specific.isConstant){
                    if(isCalcRes(q->arg1)){ // RESULT != CONSTANT
                        pop("$t1");
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE != CONSTANT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else{
                    if(isCalcRes(q->arg1)&&isCalcRes(q->arg2)){ // RESULT != RESULT
                        pop("$t2");
                        pop("$t1");

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg1)){ // RESULT != VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t1");

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg2)){ // VARIABLE != RESULT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t2");

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE != VARIABLE
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tbeq $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }
                push("$t0");
                break;

            case BOOLOP+LEQ:
                if(q->arg1->Specific.isConstant && q->arg2->Specific.isConstant){ // CONSTANT <= CONSTANT
                    if(q->arg1->Value.integer <= q->arg2->Value.integer)
                        fprintf(out, "\tli $t0, 1\n");
                    else
                        fprintf(out, "\tli $t0, 0\n");
                }else if(q->arg1->Specific.isConstant){
                    if(isCalcRes(q->arg2)){ // CONSTANT <= RESULT
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        pop("$t2");

                        fprintf(out, "\tble $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // CONSTANT <= VARIABLE
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tble $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else if(q->arg2->Specific.isConstant){
                    if(isCalcRes(q->arg1)){ // RESULT <= CONSTANT
                        pop("$t1");
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tble $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE <= CONSTANT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tble $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else{
                    if(isCalcRes(q->arg1)&&isCalcRes(q->arg2)){ // RESULT <= RESULT
                        pop("$t2");
                        pop("$t1");

                        fprintf(out, "\tble $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg1)){ // RESULT <= VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t1");

                        fprintf(out, "\tble $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg2)){ // VARIABLE <= RESULT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t2");

                        fprintf(out, "\tble $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE <= VARIABLE
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tble $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }
                push("$t0");
                break;

            case BOOLOP+GEQ:
                if(q->arg1->Specific.isConstant && q->arg2->Specific.isConstant){ // CONSTANT <= CONSTANT
                    if(q->arg1->Value.integer <= q->arg2->Value.integer)
                        fprintf(out, "\tli $t0, 1\n");
                    else
                        fprintf(out, "\tli $t0, 0\n");
                }else if(q->arg1->Specific.isConstant){
                    if(isCalcRes(q->arg2)){ // CONSTANT <= RESULT
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        pop("$t2");

                        fprintf(out, "\tbge $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // CONSTANT <= VARIABLE
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tbge $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else if(q->arg2->Specific.isConstant){
                    if(isCalcRes(q->arg1)){ // RESULT <= CONSTANT
                        pop("$t1");
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tbge $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE <= CONSTANT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tbge $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else{
                    if(isCalcRes(q->arg1)&&isCalcRes(q->arg2)){ // RESULT <= RESULT
                        pop("$t2");
                        pop("$t1");

                        fprintf(out, "\tbge $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg1)){ // RESULT <= VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t1");

                        fprintf(out, "\tbge $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg2)){ // VARIABLE <= RESULT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t2");

                        fprintf(out, "\tbge $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE <= VARIABLE
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tbge $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }
                push("$t0");
                break;

            case BOOLOP+LT:
                if(q->arg1->Specific.isConstant && q->arg2->Specific.isConstant){ // CONSTANT <= CONSTANT
                    if(q->arg1->Value.integer < q->arg2->Value.integer)
                        fprintf(out, "\tli $t0, 1\n");
                    else
                        fprintf(out, "\tli $t0, 0\n");
                }else if(q->arg1->Specific.isConstant){
                    if(isCalcRes(q->arg2)){ // CONSTANT <= RESULT
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        pop("$t2");

                        fprintf(out, "\tblt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // CONSTANT <= VARIABLE
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tblt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else if(q->arg2->Specific.isConstant){
                    if(isCalcRes(q->arg1)){ // RESULT <= CONSTANT
                        pop("$t1");
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tblt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE <= CONSTANT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tblt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else{
                    if(isCalcRes(q->arg1)&&isCalcRes(q->arg2)){ // RESULT <= RESULT
                        pop("$t2");
                        pop("$t1");

                        fprintf(out, "\tblt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg1)){ // RESULT <= VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t1");

                        fprintf(out, "\tblt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg2)){ // VARIABLE <= RESULT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t2");

                        fprintf(out, "\tblt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE <= VARIABLE
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tblt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }
                push("$t0");
                break;

            case BOOLOP+GT:
                if(q->arg1->Specific.isConstant && q->arg2->Specific.isConstant){ // CONSTANT <= CONSTANT
                    if(q->arg1->Value.integer > q->arg2->Value.integer)
                        fprintf(out, "\tli $t0, 1\n");
                    else
                        fprintf(out, "\tli $t0, 0\n");
                }else if(q->arg1->Specific.isConstant){
                    if(isCalcRes(q->arg2)){ // CONSTANT <= RESULT
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        pop("$t2");

                        fprintf(out, "\tbgt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // CONSTANT <= VARIABLE
                        fprintf(out, "\tli $t1, %d\n", q->arg1->Value.integer);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tbgt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else if(q->arg2->Specific.isConstant){
                    if(isCalcRes(q->arg1)){ // RESULT <= CONSTANT
                        pop("$t1");
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tbgt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE <= CONSTANT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tli $t2, %d\n", q->arg2->Value.integer);

                        fprintf(out, "\tbgt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }else{
                    if(isCalcRes(q->arg1)&&isCalcRes(q->arg2)){ // RESULT <= RESULT
                        pop("$t2");
                        pop("$t1");

                        fprintf(out, "\tbgt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg1)){ // RESULT <= VARIABLE
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t1");

                        fprintf(out, "\tbgt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else if(isCalcRes(q->arg2)){ // VARIABLE <= RESULT
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg2->Memory.sp);
                        pop("$t2");

                        fprintf(out, "\tbgt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }else{ // VARIABLE <= VARIABLE
                        fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp);
                        fprintf(out, "\tlw $t2, %d($s0)\n", -q->arg2->Memory.sp);

                        fprintf(out, "\tbgt $t1, $t2, _EQY_%d_\n",label); // BRANCHING ^
                        fprintf(out, "\tli $t0, 0\n");                    // BRANCHING |
                        fprintf(out, "\tj _EQN_%d_\n",label);             // BRANCHING |
                        fprintf(out, "_EQY_%d_:\n",label);                // BRANCHING |
                        fprintf(out, "\tli $t0, 1\n");                    // BRANCHING |
                        fprintf(out, "_EQN_%d_:\n",label);                // BRANCHING |
                        label++;                                          // BRANCHING v
                    }
                }
                push("$t0");
                break;

            case CONDOP+CIF:

                if(q->arg1->Specific.isConstant){ // CONSTANT
                    if(!q->arg1->Value.boolean){
                        fprintf(out, "\tj _FI_%d_\n",q->arg2->Value.integer);
                    } // else executer la suite à tout les coups
                }else if(!isCalcRes(q->arg1)){   // VARIABLE
                    fprintf(out, "\tlw $t0, %d($s0)\n", -q->arg1->Memory.sp); 
                    fprintf(out, "\tbeqz $t0,_FI_%d_\n",q->arg2->Value.integer);
                }else{                           // RESULT
                    pop("$t0");
                    fprintf(out, "\tbeqz $t0,_FI_%d_\n",q->arg2->Value.integer);
                }
                break;

            case CONDOP+CEIF:

                if(q->arg1->Specific.isConstant){ // CONSTANT
                    if(!q->arg1->Value.boolean){
                        fprintf(out, "\tj _ELSE_%d_\n",q->arg2->Value.integer);
                    } // else executer la suite à tout les coups
                }else if(!isCalcRes(q->arg1)){   // VARIABLE
                    fprintf(out, "\tlw $t0, %d($s0)\n", -q->arg1->Memory.sp); 
                    fprintf(out, "\tbeqz $t0,_ELSE_%d_\n",q->arg2->Value.integer);
                }else{                           // RESULT
                    pop("$t0");
                    fprintf(out, "\tbeqz $t0,_ELSE_%d_\n",q->arg2->Value.integer);
                }
                break;

            case CONDOP+CELSE:
                fprintf(out, "\tj _FI_%d_\n",q->arg1->Value.integer);
                fprintf(out, "_ELSE_%d_:\n",q->arg1->Value.integer);
                break;

            case CONDOP+CFI:
                fprintf(out, "_FI_%d_:\n",q->arg1->Value.integer);
                break;

            case CONDOP+CWHILE:
                fprintf(out, "_WHILE_%d_:\n",q->arg1->Value.integer);
                break;

            case CONDOP+CDO:
                if(q->arg1->Specific.isConstant){ // CONSTANT
                    if(!q->arg1->Value.boolean){
                        fprintf(out, "\tj _ENDWHILE_%d_\n",q->arg2->Value.integer);
                    } // else executer la suite à tout les coups
                }else if(!isCalcRes(q->arg1)){   // VARIABLE
                    fprintf(out, "\tlw $t0, %d($s0)\n", -q->arg1->Memory.sp); 
                    fprintf(out, "\tbeqz $t0,_ENDWHILE_%d_\n",q->arg2->Value.integer);
                }else{                           // RESULT
                    pop("$t0");
                    fprintf(out, "\tbeqz $t0,_ENDWHILE_%d_\n",q->arg2->Value.integer);
                }
                break;

            case CONDOP+CENDWHILE:
                fprintf(out, "j _WHILE_%d_\n",q->arg1->Value.integer);
                fprintf(out, "_ENDWHILE_%d_:\n",q->arg1->Value.integer);
                break;

            case CONDOP+CFOR:
                
                fprintf(out, "\tlw $t0, %d($s0)\n", -q->res->Memory.sp); 
                fprintf(out, "\taddi $t0, $t0, -1\n");
                fprintf(out, "\tsw $t0, %d($s0)\n", -q->res->Memory.sp); 

                fprintf(out, "_FOR_%d_:\n",q->arg2->Value.integer);

                fprintf(out, "\tlw $t0, %d($s0)\n", -q->res->Memory.sp); 
                fprintf(out, "\taddi $t0, $t0, 1\n");
                fprintf(out, "\tsw $t0, %d($s0)\n", -q->res->Memory.sp); 

                if(q->arg1->Specific.isConstant) // CONSTANT
                    fprintf(out, "\tli $t1, %d\n",q->arg1->Value.integer);
                else if(!isCalcRes(q->arg1))     // VARIABLE
                    fprintf(out, "\tlw $t1, %d($s0)\n", -q->arg1->Memory.sp); 
                else                             // RESULT
                    pop("$t1");
                
                fprintf(out, "\tlw $t0, %d($s0)\n", -q->res->Memory.sp);
                fprintf(out, "\tbge $t0, $t1, _ENDFOR_%d_\n",q->arg2->Value.integer);
                break;

            case CONDOP+CENDFOR:
                fprintf(out, "\tj _FOR_%d_\n",q->arg1->Value.integer);
                fprintf(out, "_ENDFOR_%d_:\n",q->arg1->Value.integer);
                break;

            case '=':
                if(q->res==NULL){
                    fprintf(out, "\taddi $sp, $sp, 4\n"); // Unstacking the unused value
                    break;
                }
                if(q->arg1->Specific.isConstant) // CONSTANT
                    fprintf(out, "\tli $t0, %d\n", q->arg1->Value.integer);
                else if(!isCalcRes(q->arg1))     // VARIABLE
                    fprintf(out, "\tlw $t0, %d($s0)\n", -q->arg1->Memory.sp); 
                else{                            // RESULT
                    fprintf(out, "\tlw $t0, 0($sp)\n");
                    fprintf(out, "\taddi $sp, $sp, 4\n");
                }
                fprintf(out, "\tsw $t0, %d($s0)\n", -q->res->Memory.sp);
                break;
        }
    }
    fclose(out);
}
